package engine;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;

public final class GameManager implements Runnable {

	final static long SLEEP_TIME = 17;
	static volatile GameManager gameManager;
	volatile Component canvas;
	volatile Thread animationThread;
	volatile GameState currentState;
	volatile GameState nextState;
	volatile boolean running;
	volatile boolean paused;

	private GameManager() {

	}

	public static GameManager getInstance() {
		if (gameManager == null) {
			gameManager = new GameManager();
			Logger.log("FPS", SLEEP_TIME);
		}
		return gameManager;
	}

	public final Component getCanvas() {
		return canvas;
	}

	public final void setCanvas(Component canvas) {
		this.canvas = canvas;
	}

	public final boolean isPaused() {
		return paused;
	}

	public final void pause() {
		this.paused = true;
	}

	public final void unpause() {
		this.paused = false;
	}

	public final void togglePause() {
		paused = !paused;
	}

	public final void startGame() {
		running = true;
		if (animationThread == null) {
			animationThread = new Thread(this);
			animationThread.start();
		}
	}

	void addListeners(GameState state) {
		Logger.log("Added Listeners");
		canvas.addMouseListener(state);
		canvas.addKeyListener(state);

	}

	void removeListeners(GameState state) {
		canvas.removeMouseListener(state);
		canvas.removeKeyListener(state);
	}

	public final void stopGame() {
		running = false;
	}

	public final void loadNextState(final GameState nextState) {
		this.nextState = nextState;
		new Thread() {
			public void run() {
				final GameState oldState = currentState;
				if (nextState != null) {
					nextState.load();
					nextState.init();
				}
				removeListeners(oldState);
				addListeners(nextState);
				currentState = nextState;
				if (oldState != null) {
					oldState.unload();
				}
			};
		}.start();
	}

	@Override
	public void run() {
		final int canvasWidth = canvas.getWidth();
		final int canvasHeight = canvas.getHeight();
		final Image buffer = canvas.createImage(canvasWidth, canvasHeight);
		final Graphics bufferGraphics = buffer.getGraphics();
		Graphics mainGraphics = null;
		System.out.println(canvasWidth + " " + canvasHeight);

		try {
			while (running) {
				if (!paused) {

					bufferGraphics.setColor(Color.BLACK);
					bufferGraphics.fillRect(0, 0, canvasWidth, canvasHeight);

					if (currentState != null) {
						currentState.update(0);
						currentState.paint(bufferGraphics);
					}
					mainGraphics = canvas.getGraphics();
					mainGraphics.drawImage(buffer, 0, 0, null);
					Toolkit.getDefaultToolkit().sync();
					mainGraphics.dispose();
				}
				Thread.sleep(SLEEP_TIME);
			}
		} catch (InterruptedException e) {
			Logger.log(e);
		}
	}
}
